// Copyright [year] <Copyright Owner>
#ifndef _FRAME_PARSER_H_  // NOLINT
#define _FRAME_PARSER_H_

#include <vector>
#include <algorithm>
#include <iterator>
#include <utility>

#include<iomanip>
#include <iostream>
#include<bitset>

template <typename T>
class FrameParser {
 public:
    FrameParser(const std::vector<T> &headTag, const std::vector<T> &tailTag, const bool discardTag = true)
        : frameHeadTag(headTag), frameTailTag(tailTag), discardFrameTag{ discardTag }
    {}

    bool isDiscardFrameTag() const {
        return discardFrameTag;
    }

    template<class It>
    void append(It f, It l) {
        buffer.insert(buffer.end(), f, l);
    }
    void append(const std::vector<T> &data) {
        buffer.insert(buffer.end(), data.cbegin(), data.cend());
    }

    void parse(std::vector<std::vector<T>>& frames) {  // NOLINT
        auto it_head{ buffer.cbegin() };
        for (auto it_tail{ std::search(it_head, buffer.cend(), frameTailTag.cbegin(), frameTailTag.cend()) };
            it_tail != buffer.cend(); it_tail = std::search(it_head, buffer.cend(), frameTailTag.cbegin(), frameTailTag.cend())) {
            it_head = std::search(it_head, it_tail, frameHeadTag.cbegin(), frameHeadTag.cend());
            if (it_head != it_tail) {
                frames.emplace_back(isDiscardFrameTag() ? it_head + frameHeadTag.size() : it_head
                    , isDiscardFrameTag() ? it_tail : it_tail + frameTailTag.size());
            }
            it_head = std::next(it_tail, frameTailTag.size());
        }

        tempBuffer.insert(tempBuffer.end(), it_head, buffer.cend());
        // std::cout << "tempbuff size = " << tempBuffer.size() << std::endl;
        // for (auto data : tempBuffer)
        //   // std::cout << std::hex << data << " ";
        //   printf("0x%02x ", data);
        std::cout << std::endl;
        std::swap(buffer, tempBuffer);
        tempBuffer.clear();
    }
    // std::vector<T> buffer;

 private:
    bool discardFrameTag{ true };
    const std::vector<T> frameHeadTag;
    const std::vector<T> frameTailTag;
    std::vector<T> buffer;
    std::vector<T> tempBuffer;
};

#endif  // _FRAME_PARSER_H_  // NOLINT
